import cv2
import numpy as np
import matplotlib.pyplot as plt 
def CV_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
def sort_contours(cnts, method="left-to-right"):
    # 初始化反向标志和排序索引
    reverse = False
    i = 0
    # 按从下到上排序
    if method == "bottom-to-top":
        reverse = True
        i = 1
    # 按从右到左排序
    elif method == "right-to-left":
        reverse = True
        i = 0

    boundingBoxes = [cv2.boundingRect(c) for c in cnts]
    (cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
                                        key=lambda b: b[1][i], reverse=reverse))
    return cnts, boundingBoxes

def resize(image, width=300):
    # 获取原始图像的高、宽
    (h, w) = image.shape[:2]  
    # 计算缩放比例（基于宽度）
    r = width / float(w)  
    # 计算缩放后的高度（保持宽高比）
    new_h = int(h * r)  
    # 执行缩放（使用 INTER_AREA 算法，适合缩小图像）
    resized = cv2.resize(image, (width, new_h), interpolation=cv2.INTER_AREA)
    return resized
    
# 读取图像（灰度模式）
image = cv2.imread('152_1753154394_hd.jpeg', cv2.IMREAD_GRAYSCALE)  

# 二值化（用 Otsu 自动阈值）
ret, ref = cv2.threshold(image, 10, 255, cv2.THRESH_BINARY_INV)  
# 提取轮廓（新版 OpenCV 返回 2 个值）
contour, hierangchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  

# 调试：打印轮廓数量
print(f"提取到 {len(contour)} 个轮廓")  

# 转成彩色图，方便显示红色轮廓
ref_color = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)  

# 画轮廓（红色，线宽 2）
cv2.drawContours(ref_color, contour, -1, (0, 0, 255), 2)  

contours,Boundingboxes=sort_contours(contour,"left-to-right")
digits={}
for (i,c) in enumerate(contours):
    x,y,w,h=cv2.boundingRect(c)
    roi=image[y:y+h,x:x+w]
    roi=cv2.resize(roi,(57,58))
    digits[i]=roi
rectkernel=cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
sqkernel=cv2.getStructuringElement(cv2.MORPH_RECT,(10,5))

image1 = cv2.imread('149_1753154392_hd.jpeg', cv2.IMREAD_GRAYSCALE)  
image1=resize(image1,300)
tophat=cv2.morphologyEx(image1,cv2.MORPH_TOPHAT,rectkernel)
gradx=cv2.Sobel(tophat,cv2.CV_32F,dx=1,dy=0,ksize=-1)
#gradx=cv2.convertScaleAbs(gradx)
#grady=cv2.Sobel(tophat,cv2.CV_64F,dx=0,dy=1,ksize=-1)
#grady=cv2.convertScaleAbs(grady)
#gradxy=cv2.addWeighted(gradx,0.5,grady,0.5,0)
gradX = np.absolute(gradx)  # 取绝对值，把负梯度转成正的
(minVal, maxVal) = (np.min(gradX), np.max(gradX))  
gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))  # 归一化到 0-255
gradX = gradX.astype("uint8")  # 转成 uint8 类型（图像标准格式）
gradxy=cv2.morphologyEx(gradX,cv2.MORPH_CLOSE,sqkernel)
ret,thresh=cv2.threshold(gradxy,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)
j=0
while(j<5):
    thresh=cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,sqkernel)
    j+=1
cnts,ol=cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cur_image=image1.copy()

locs=[]
for (i,c) in enumerate(cnts):
   # 计算轮廓外接矩形及宽高比
    (x, y, w, h) = cv2.boundingRect(c)
    ar = w / float(h)  

# 根据宽高比和尺寸筛选轮廓
    if ar > 2.5 and ar < 4.0:
        if (w > 40 and w < 55) and (h > 10 and h < 20):
            locs.append((x, y, w, h))

# 对筛选出的轮廓按 x 坐标排序
locs = sorted(locs, key=lambda x: x[0])  
output=[]
for(i,(gx,gy,gw,gh)) in enumerate(locs):
    groupoutput=[]
    group=cur_image[gy-5:gy+gh+5,gx-5:gx+gw+5]
    ret,group=cv2.threshold(group,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)
    bianyuan,dl=cv2.findContours(group.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    bianyuan,_=sort_contours(bianyuan,"left-to-right")
    for (j, c) in enumerate(bianyuan):
        if len(c) == 0:
            continue  # 跳过空轮廓
        # 转换为 OpenCV 兼容格式
        c = np.array(c, dtype=np.int32)
        x, y, w, h = cv2.boundingRect(c)
        roi=image[y:y+h,x:x+w]
        roi=cv2.resize(roi,(57,58))
        scores=[]
        for(digit,digitROI) in digits.items():
            result=cv2.matchTemplate(roi,digitROI,cv2.TM_CCOEFF)
            (_,score,_,_)=cv2.minMaxLoc(result)
            scores.append(score)
        groupoutput.append(str(np.argmax(scores)))
    cv2.rectangle(image1,(gx-5,gy-5),
                  (gx+gw+5,gy+gh+5),(0,0,255),2)
    cv2.putText(image1,"".join(groupoutput),(gx,gy-15),
                cv2.FONT_HERSHEY_SIMPLEX,0.65,(0,0,255),2)
    output.extend(groupoutput)


print(output[0])
print((output))
CV_show('image',image1)
